package com.wtgroup.demo.mianshi.线程.d02_condition_await_signal;

import com.wtgroup.demo.common.util.SleepUtil;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author dafei
 * @version 0.1
 * @date 2021/3/7 16:51
 */
public class D2_BoundedQueue {

    public static void main(String[] args) throws InterruptedException {
        D2_BoundedQueue d = new D2_BoundedQueue();

        Thread t1 = new Thread(() -> {
            d.remove(); // 预期阻塞
            d.remove();
        });
        Thread t2 = new Thread(() -> {
            SleepUtil.sleep(2);
            for (int i = 0; i < 10; i++) {
                d.put(i);
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("!!!!!!!!!!!!!!!");
    }

    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();
    // 有界队列
    private Object[] queue = new Object[5];
    private int addIndex,removeIndex,count;

    // 生产
    public void put(Object item) {
        lock.lock();
        try {
            while (count == queue.length) {
                System.out.println("[put] to await");
                notFull.await();
                System.out.println("[put] end await");
            }
            queue[addIndex] = item;
            count++;
            if (++addIndex==queue.length) {
                addIndex = 0;
            }
            // 必定非空了, 通知消费者
            notEmpty.signal();
            // TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private Object remove() {
        Object ret = null;
        lock.lock();
        try {
            while (count == 0) {
                System.out.println("[remove] to await");
                notEmpty.await();
                System.out.println("[remove] end await");
            }
            ret = queue[removeIndex];
            if (++removeIndex == queue.length) {
                removeIndex = 0;
            }
            count--;
            // 必定没满, 通知生产者
            notFull.signal();
            // TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return ret;
    }
}
